(function(init){
	//window拓展对象监测
	["Store","Cookie"].forEach(function(name,i,arr){
		if(name in window){
			throw new Error("已存在"+name+"拓展对象");
		}
	})
	init();
})(function(){
	"use strict";
	//storage模块
	var Storage=(function(){
		var methods={};
		var cache={};
		//缓存对象和时间确定
		function analysis(args){
			var obj=Tool.merge(args,{type:0,time:0});
			if(obj.type===0){
				cache=window.localStorage;
			}else if(obj.type===1){
				cache=window.sessionStorage;
			}else{
				throw new Error("类型值传递只能为数值0和1");
			}
			if(Tool.type(obj.time)==="number"){
				if(obj.time<0){
					obj.time=0;
				}
				return obj;
			}else{
				throw new Error("时间只能传递数值类型");
			}
		}
		//过期缓存检测
		function detection(){
			for(var i in localStorage){
				if(/^\{.*\}$/.test(localStorage[i])){
					var oldTime=Number(JSON.parse(localStorage[i]).time);
					if(oldTime){
						var newTime=new Date().getTime();
						if(newTime>oldTime){
							localStorage.removeItem(i);
						}
					}
				}
			}
			return methods;
		}
		//取值
		methods.get=function(key,obj){
			Tool.keyJudge(key);
			analysis(obj);
			if(key==="*"){
				var o={};
				for(var i in cache){
					o[i]=Tool.strJSON(cache[i]);
				}
				return o;
			}
			var val=cache.getItem(key);
			return Tool.strJSON(val);
		}
		//赋值
		methods.set=function(key,val,obj){
			Tool.keyJudge(key);
			var args=analysis(obj);
			var o={
				data:typeof(val)==="function"?String(val):val,
				type:"cache"
			};
			if(args.time>0&&args.type===0){
				var d=new Date();
				o.time=d.setTime(d.getTime()+args.time*1000);
			}
			cache.setItem(key,JSON.stringify(o));
			return this;
		}
		//删除
		methods.remove=function(key,obj){
			Tool.keyJudge(key);
			var o=this.get(key,obj);
			(key==="*")?cache.clear():cache.removeItem(key);
			return o;
		}
		//清空
		methods.clear=function(obj){
			if(obj){
				return this.remove("*",obj);
			}else{
				return [this.remove("*",{type:0}),this.remove("*",{type:1})];
			}
		}
		//是否存在
		methods.has=function(key,obj){
			Tool.keyJudge(key);
			analysis(obj);
			return (key in cache)?true:false;
		}
		return detection();
	})();
	//cookie模块
	var Cookie = (function(){
		var methods={};
		//取值
		methods.get=function(key) {
			Tool.keyJudge(key);
			var obj={};
			var all = document.cookie.split(';');
			all.forEach(function(str,i,arr){
				var arr=str.trim().split('=');
				var key=arr[0];
				var val=arr[1];
				obj[key]=Tool.strJSON(val);
			})
			if(key==="*"){
				return obj;
			}
			if(key in obj){
				return obj[key];
			}
		},
		//赋值
		methods.set=function(key, val, time) {
			Tool.keyJudge(key);
			var expires="";
			var value="";
			if(time){
				var d = new Date();
				d.setTime(d.getTime() + time*1000);
				expires="expires=" + d.toUTCString();
			}
			if(typeof(val)==="function"){
				value=String(val);
			}else if(typeof(val)==="string"){
				value=val;
			}else{
				value=JSON.stringify(val);
			}
			document.cookie = key + "=" + value + "; " + expires;
			return this;
		},
		//删除
		methods.remove=function(key){
			var obj=this.get(key);
			var expires="=;expires=Thu, 01 Jan 1970 00:00:00 GMT";
			if(key==="*"){
				for(var i in obj){
					document.cookie=i+expires;
				}
			}else{
				document.cookie=key+expires;
			}
			return obj;
		},
		//清除
		methods.clear=function(){
			return this.remove("*");
		},
		//是否存在
		methods.has=function(key){
			var val=this.get(key);
			return val?true:false;
		}
		return methods;
	})();
	//工具类模块
	var Tool={
		//get值转换
		strJSON:function(val){
			if(/^\{.*\}$/.test(val)){
				var obj=JSON.parse(val);
				return (obj.type==="cache")?obj.data:obj;
			}else if(/^\[.*\]$/.test(val)||/^\d+$/.test(val)||/null/.test(val)){
				return JSON.parse(val);
			}else{
				return val;
			}
		},
		//对象合并
		merge:function(obj,options){
			if(obj){
				for(var i in options){
					if(i in obj){
						options[i]=obj[i];
					}
				}
			}
			return options;
		},
		//类型判断
		type:function(val){
			val = Object.prototype.toString.call(val).toLowerCase();
	        return val.replace(/(\[object\s)|(\])/g, "");
		},
		//键名类型判断
		keyJudge:function(key){
			if(key===undefined){
				throw new Error("键名不能为空");
			}else if(typeof(key)!=="string"){
				throw new Error("键名必须为字符串类型");
			}
		}
	}
	window.Storage=Storage;
	window.Cookie=Cookie;
})
